/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tom.social.dal;

import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import pl.tom.social.dal.entity.Profile;
import pl.tom.social.dal.entity.Site;
import pl.tom.social.dal.entity.SiteEntry;
import pl.tom.social.dal.entity.SiteEntryComment;
import pl.tom.social.dal.entity.SiteLink;
import pl.tom.social.dal.entity.SiteSiteLink;
import pl.tom.social.dal.entity.TermResult;

/**
 *
 * @author Tom
 */
public class SocialDatabaseFacade {

	private static final EntityManagerFactory mgrFactory = Persistence.createEntityManagerFactory("SocialPU");
	private EntityManager mgr = null;

	public SocialDatabaseFacade() {
	}

	@Override
	protected void finalize() throws Throwable {
		if (mgr != null && mgr.isOpen()) {
			mgr.close();
		}
		super.finalize();
	}

	public EntityManager getEntityManager() {
		if (mgr == null || !mgr.isOpen()) {
			mgr = mgrFactory.createEntityManager();
		}
		return mgr;
	}

	public Object mergeEntity(Object entity) {
		final EntityManager em = getEntityManager();
		final EntityTransaction et = em.getTransaction();

		try {
			et.begin();
			em.merge(entity);
			et.commit();
		} finally {
			if (et != null && et.isActive()) {
				entity = null;
				et.rollback();
			}
		}

		return entity;
	}

	public Object persistEntity(Object entity) {
		final EntityManager em = getEntityManager();
		final EntityTransaction et = em.getTransaction();

		try {
			et.begin();
			em.persist(entity);
			et.commit();
		} finally {
			if (et != null && et.isActive()) {
				entity = null;
				et.rollback();
			}
		}

		return entity;
	}

	public void deleteEntity(Object entity) {
		final EntityManager em = getEntityManager();
		final EntityTransaction et = em.getTransaction();

		try {
			et.begin();
			em.remove(entity);
			et.commit();
		} finally {
			if (et != null && et.isActive()) {
				entity = null;
				et.rollback();
			}
		}
	}

	public List<Site> getAllSites() {
		return getEntityManager().createNamedQuery("Site.findAll").getResultList();
	}

	public Long getSitesNr() {
		List<Long> list = getEntityManager().createNamedQuery("Site.countAll").getResultList();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return 0l;
	}

	public List<String> getAllSitesUrls() {
		return getEntityManager().createNamedQuery("Site.findAllUrls").getResultList();
	}

	public Site getSiteForUpdate() {
		List<Site> siteList = getEntityManager().createNamedQuery("Site.findAllByUpdate").setMaxResults(1).
			getResultList();
		if (siteList.isEmpty()) {
			return null;
		}
		return siteList.get(0);
	}

	public Site getSite(String url) throws Exception {
		List<Site> list = getEntityManager().createNamedQuery("Site.findByUrl").setParameter("url",
			url).getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (Site site : list) {
				buffer.append("id:" + site.getId() + " url:" + site.getUrl() + "\n");
			}
			throw new Exception("Two sites with the same url. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}

	public Site getOldestSite() {
		List<Site> list = getEntityManager().createNamedQuery("Site.findAllByUpdate").setMaxResults(1).getResultList();
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	public Site getNewestSite() {
		List<Site> list = getEntityManager().createNamedQuery("Site.findNewest").setMaxResults(1).getResultList();
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	public Long getSiteLinksNr(Site site) {
		List<SiteSiteLink> list = getEntityManager().createNamedQuery("SiteSiteLink.findBySiteId").setParameter("siteId", site.getId()).
			getResultList();
		if (!list.isEmpty()) {
			return (long)list.size();
		}
		return 0l;
	}

	public List<String> getAllSiteLinksUrlsBetween(Date start, Date end) {
		return getEntityManager().createNamedQuery("SiteSiteLink.findAllBetween").setParameter("start", start).setParameter(
			"end", end).getResultList();
	}

	public List<String> getSiteLinksUrls(Site site) {
		List<String> siteList = getEntityManager().createNamedQuery("SiteSiteLink.getUrlsBySite").setParameter("siteId", site.getId()).
			getResultList();

		return siteList;
	}

	public SiteLink getSiteLink(String url) throws Exception {
		List<SiteLink> list = getEntityManager().createNamedQuery("SiteLink.findByUrl").
			setParameter("url", url).getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (SiteLink link : list) {
				buffer.append("id:" + link.getId() + " url:" + link.getUrl() + "\n");
			}
			throw new Exception("Two sites with the same url. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}

	public SiteSiteLink getOldestSiteLink() {
		List<SiteSiteLink> list = getEntityManager().createNamedQuery("SiteSiteLink.findAll").setMaxResults(1).getResultList();
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	public SiteSiteLink getNewestSiteLink() {
		List<SiteSiteLink> list = getEntityManager().createNamedQuery("SiteSiteLink.findNewest").setMaxResults(1).getResultList();
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	public List<SiteLink> getLikeServerSiteLink(String server) {
		return getEntityManager().createNamedQuery("SiteLink.findLikeServer").setParameter("server",
			"%" + server.toUpperCase() + "%").getResultList();
	}

	public SiteSiteLink getSiteLinkSitePK(Site site, SiteLink siteLink) {
		List<SiteSiteLink> list = getEntityManager().createNamedQuery("SiteSiteLink.findBySiteIdAndSiteLinkId").setParameter("siteId", site.getId()).setParameter("siteLinkId", siteLink.getId()).getResultList();
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	public SiteEntry getSiteEntry(String url) throws Exception {
		List<SiteEntry> list = getEntityManager().createNamedQuery("SiteEntry.findByUrl").setParameter("url", url).
			getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (SiteEntry entry : list) {
				buffer.append("id:" + entry.getId() + " url:" + entry.getUrl() + "\n");
			}
			throw new Exception("Two siteEntries with the same url. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}

	public SiteEntry getSiteEntry(Integer id) throws Exception {
		List<SiteEntry> list = getEntityManager().createNamedQuery("SiteEntry.findById").setParameter("id", id).
			getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (SiteEntry entry : list) {
				buffer.append("id:" + entry.getId() + " url:" + entry.getUrl() + "\n");
			}
			throw new Exception("Two siteEntries with the same id. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}

	public List<SiteEntry> getSiteEntries(Site site) {
		return getEntityManager().createNamedQuery("SiteEntry.findBySite").setParameter("site", site).getResultList();
	}

	public List<Integer> getSiteEntryIds(Site site) {
		return getEntityManager().createNamedQuery("SiteEntry.findIdsBySite").setParameter("site", site).getResultList();
	}

	public Long getSiteEntriesNr() {
		List<Long> list = getEntityManager().createNamedQuery("SiteEntry.countAll").getResultList();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return 0l;
	}

	public Long getSiteEntriesNr(Site site) {
		List<Long> list = getEntityManager().createNamedQuery("SiteEntry.countAllBySite").setParameter("site", site).
			getResultList();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return 0l;
	}

	public List<SiteEntryComment> getSiteEntryComments(SiteEntry entry) {
		return getEntityManager().createNamedQuery("SiteEntryComment.findBySiteEntry").setParameter("siteEntry", entry).
			getResultList();
	}

	public SiteEntryComment getSiteEntryComment(String url) throws Exception {
		List<SiteEntryComment> list = getEntityManager().createNamedQuery("SiteEntryComment.findByUrl").setParameter(
			"url", url).getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (SiteEntryComment comment : list) {
				buffer.append("id:" + comment.getId() + " term:" + comment.getUrl() + "\n");
			}
			throw new Exception("Two SiteEntryComments with the same url. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}

	public Long getSiteEntryCommentsNr() {
		List<Long> list = getEntityManager().createNamedQuery("SiteEntryComment.countAll").getResultList();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return 0l;
	}

	public Long getSiteEntryCommentsNr(SiteEntry entry) {
		List<Long> list = getEntityManager().createNamedQuery("SiteEntryComment.countAllBySiteEntry").setParameter(
			"siteEntry", entry).getResultList();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return 0l;
	}

	public TermResult getTermResult(String term) throws Exception {
		List<TermResult> termList = getEntityManager().createNamedQuery("TermResult.findByTerm").setParameter("term",
			term).getResultList();
		if (termList.isEmpty()) {
			return null;
		} else if (termList.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (TermResult termResult : termList) {
				buffer.append("id:" + termResult.getId() + " term:" + termResult.getTerm() + "\n");
			}
			throw new Exception("Two TermResults with the same term. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return termList.get(0);
	}

	public List<Profile> getAllProfiles() {
		return getEntityManager().createNamedQuery("Profile.findAll").getResultList();
	}

	public Profile getProfile(String name) throws Exception {
		List<Profile> list = getEntityManager().createNamedQuery("Profile.findByName").setParameter("name", name).getResultList();
		if (list.isEmpty()) {
			return null;
		} else if (list.size() > 1) {
			StringBuffer buffer = new StringBuffer();
			for (Profile p : list) {
				buffer.append("id:" + p.getId() + " name:" + p.getName() + "\n");
			}
			throw new Exception("Two Profiles with the same name. This is sooooo SAD. Here they go:\n" + buffer.toString());
		}
		return list.get(0);
	}
}
